package org.zhadoop.stream.cql.semanticanalyzer.parser.context;

import static org.hamcrest.CoreMatchers.instanceOf;

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.zhadoop.stream.api.streams.Column;
import org.zhadoop.stream.api.streams.Schema;
import org.zhadoop.stream.cql.exception.SemanticAnalyzerException;
import org.zhadoop.stream.cql.semanticanalyzer.BaseAnalyzer;
import org.zhadoop.stream.cql.semanticanalyzer.analyzecontext.expressiondesc.ExpressionDescribe;
import org.zhadoop.stream.cql.semanticanalyzer.analyzecontext.expressiondesc.PropertyValueExpressionDesc;
import org.zhadoop.stream.cql.semanticanalyzer.parsecontextreplacer.ParseContextReplacer;
import org.zhadoop.stream.cql.semanticanalyzer.parsecontextwalker.ParseContextWalker;
import org.zhadoop.streaming.exception.ErrorCode;

/**
 * 原子表达式的解析内容
 * 
 * @author zwd
 *
 */
public class AtomExpressionContext extends BaseExpressionParseContext {

	private static final Logger LOG = LoggerFactory.getLogger(AtomExpressionContext.class);

	private BaseExpressionParseContext constant;

	private BaseExpressionParseContext function;

	private BaseExpressionParseContext castExpression;

	private BaseExpressionParseContext caseExpression;

	private BaseExpressionParseContext whenExpression;

	private String columnName;

	private BaseExpressionParseContext expressionWithLaparen;

	private BaseExpressionParseContext previous;

	@Override
	public void walkChildAndReplace(ParseContextReplacer replacer) {
		// TODO Auto-generated method stub

	}

	@Override
	protected ExpressionDescribe createExpressionDesc() throws SemanticAnalyzerException {
		if (constant != null) {

		}

		if (columnName != null) {
			int index = foundIndex();
			Schema schema = null;

			if (getLeftExpression() != null) {
				if (getLeftExpression() instanceof FieldExpressionContext) {
					FieldExpressionContext fieldExp = (FieldExpressionContext) getLeftExpression();
					if (fieldExp.getStreamNameOrAlias() != null) {
						schema = BaseAnalyzer.getSchemaByName(fieldExp.getStreamNameOrAlias(), getSchemas());
					}
				}
			}
			List<Column> attrs = getAttributeByName(columnName, schema);

			validateColumns(attrs);
			
			if(schema != null){
				return new PropertyValueExpressionDesc(attrs.get(0), schema.getId(), index);
			}

		}
		return null;
	}

	private void validateColumns(List<Column> attrs) throws SemanticAnalyzerException {
		if (attrs.size() > 1) {
			SemanticAnalyzerException exception = new SemanticAnalyzerException(
					ErrorCode.SEMANTICANALYZE_DUPLICATE_COLUMN_ALLSTREAM, columnName);
			LOG.error(ErrorCode.SEMANTICANALYZE_DUPLICATE_COLUMN_ALLSTREAM.getFullMessage(columnName), exception);
			throw exception;
		}
		if (attrs.size() == 0) {
			SemanticAnalyzerException exception = new SemanticAnalyzerException(
					ErrorCode.SEMANTICANALYZE_NO_COLUMN_ALLSTREAM, columnName);
			LOG.error(ErrorCode.SEMANTICANALYZE_NO_COLUMN_ALLSTREAM.getFullMessage(columnName), exception);
			throw exception;
		}

	}

	private int foundIndex() throws SemanticAnalyzerException {
		int index = 0;
		if (getLeftExpression() != null) {
			if (getLeftExpression() instanceof FieldExpressionContext) {
				FieldExpressionContext fieldExp = (FieldExpressionContext) getLeftExpression();
				if (fieldExp.getStreamNameOrAlias() != null) {
					index = getIndexInSchemas(fieldExp.getStreamNameOrAlias());
				}
			}
		}
		return index;
	}

	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder();
		if (constant != null) {
			sb.append(constant.toString());
		}
		if (function != null) {
			sb.append(function.toString());
		}
		if (castExpression != null) {
			sb.append(castExpression.toString());
		}
		if (caseExpression != null) {
			sb.append(caseExpression.toString());
		}
		if (whenExpression != null) {
			sb.append(whenExpression.toString());
		}
		if (columnName != null) {
			sb.append(columnName);
		}
		if (expressionWithLaparen != null) {
			sb.append(expressionWithLaparen);
		}
		if (previous != null) {
			sb.append(previous);
		}
		return sb.toString();
	}

	@Override
	protected void walkChild(ParseContextWalker walker) {
		// TODO Auto-generated method stub

	}

	public BaseExpressionParseContext getConstant() {
		return constant;
	}

	public void setConstant(BaseExpressionParseContext constant) {
		this.constant = constant;
	}

	public BaseExpressionParseContext getFunction() {
		return function;
	}

	public void setFunction(BaseExpressionParseContext function) {
		this.function = function;
	}

	public BaseExpressionParseContext getCastExpression() {
		return castExpression;
	}

	public void setCastExpression(BaseExpressionParseContext castExpression) {
		this.castExpression = castExpression;
	}

	public BaseExpressionParseContext getCaseExpression() {
		return caseExpression;
	}

	public void setCaseExpression(BaseExpressionParseContext caseExpression) {
		this.caseExpression = caseExpression;
	}

	public BaseExpressionParseContext getWhenExpression() {
		return whenExpression;
	}

	public void setWhenExpression(BaseExpressionParseContext whenExpression) {
		this.whenExpression = whenExpression;
	}

	public String getColumnName() {
		return columnName;
	}

	public void setColumnName(String columnName) {
		this.columnName = columnName;
	}

	public BaseExpressionParseContext getExpressionWithLaparen() {
		return expressionWithLaparen;
	}

	public void setExpressionWithLaparen(BaseExpressionParseContext expressionWithLaparen) {
		this.expressionWithLaparen = expressionWithLaparen;
	}

	public BaseExpressionParseContext getPrevious() {
		return previous;
	}

	public void setPrevious(BaseExpressionParseContext previous) {
		this.previous = previous;
	}

}
